Retrofit2 代理请求解析
前言
Retrofit 是一个网络请求框架,它可以将 HTTP API 转换成 Java 中的接口,通过其灵活的设计模式将底层的网络请求和上传的业务封装结合起来,使网络调用变得十分简单
这篇文章的目的就是深入解读 Retrofit2 是如何采用各种各样的设计模式来完成仅仅通过接口的定义来完成复杂的网络请求
基本使用
Retrofit 将 HTTP API 转化为 Java 接口
1 | public interface GitHubService { |
Retrofit 类去生成一个 GitHubService 接口的实现
1 | Retrofit retrofit = new Retrofit.Builder() |
GitHubService 实现中的每个 Call 都能实现同步或则异步的HTTP 请求
1 | Call<List<Repo>> repos = service.listRepos("octocat"); |
流程解析
流程的关键在于 Retrofit 是如何处理 API 接口的实现,我们可以通过 Retrofit.create 方法去深入探究
Retrofit.create 方法
1 | public <T> T create(final Class<T> service) { |
Retrfit 采用了动态代理模式,当调用接口的方法时,会动态地由 InvocationHandler.invoke 去实现具体的逻辑,而 Retrofit 里面最主要的是构建 ServiceMethod 对象的工作,对于请求的一些参数,封装都是由这个对象持有的,而构建过程则是在 Retrfit.loadServiceMethod 方法中
Retrfit.loadServiceMethod 方法
1 | ServiceMethod<?, ?> loadServiceMethod(Method method) { |
ServiceMethod 的构造过程需要两个参数,一个是 Retrofit 对象,用来获取用户构造 Retrofit 对象时传入的一些配置,另一个就是 Method 对象,用来获取具体的接口配置参数,最终在 ServiceMethod.Builder.build 方法中创建 ServiceMethod 对象
ServiceMethod.Builder.build 方法
该方法比较长,所以会选择性略去一些代码
1 | public ServiceMethod build() { |
关于 callAdapter 和 responseConverter 后面会讲到,这写先跟踪 parseMethodAnnotation 方法去找到如何将注解转化到请求参数里
ServiceMethod.Builder.parseMethodAnnotation 方法
1 | private void parseMethodAnnotation(Annotation annotation) { |
每个注解类型都有对应的解析方法,深入到 parseHttpMethodAndPath 方法里可以得知 ServiceMethod 从注解中获取了 httpMethod,hasBody 属性,还通过正则去获取了 relativeUrl,relativeUrlParamNames(这个是一个 Set
在得到了 ServiceMethod 得到所有请求相关参数后,回到 Retrofit.create 方法那边,会封装出一个 new OkHttpCall<>(serviceMethod, args),而真正的 okhttp 请求对象则是在 OkHttpCall.createRawCall 方法里生成的,这个方法中又调用了传入的 ServiceMethod 对象的 toCall 方法,所以请求的生成也是交由 ServiceMethod 控制的,无非是将传入的参数与解析出来的请求参数合并生成一个 okhttp 请求体 okhttp3.Call,最后再通过 ServiceMethod 中的 callAdapter 进行流程封装,真正触发网络请求
CallAdapter & Converter
CallAdapter 是 Retrofit 的网络执行器,负责创建 okhttp 的网络请求对象,发送网络请求,而 Converter 则是 Retrofit 的数据解析器,负责数据转换解析。
这两者都是通过策略模式实现的,我们可以通过官方提供的 adapter-rxjava2 以及 converter-gson 两种实现来使用 rxjava2 来调用 Retrofit 的接口请求以及通过 gson 将接口的 json 数据转化为对象。而对应实例生成也用到抽象工厂模式。在 Retrofit 中定义了 CallAdapter 和 Converter 接口以及抽象工厂类。
我们通过 adapter-rxjava2 和 converter-gson 两个包的引入来具体分析 Retrofit 的网络请求流程。
1 | Retrofit retrofit = new Retrofit.Builder() |
不涉及到具体的 CallAdapterFactory 时,网络请求通过 ServiceMethod.adapt 方法,传入 OkHttpCall 对象,最终
通过 ServiceMethod 中持有的 CallAdapter 的 adapt 方法执行
ServiceMethod 中持有的 CallAdapter(Retrofit 中传入工厂类,最终会根据 returnType 得到真正的 CallAdapter)进行真正的网络请求,在 RxJava2CallAdapterFactory.get 方法中,我们得到真正的 RxJava2CallAdapter 类)继续追踪 adapt 方法
RxJava2CallAdapter.adapt 方法
1 |
|
生成一个 observable,根据设定进行额外的处理,最终返回我们想要的数据类型,这里我们以同步请求 CallExecuteObservable 为例继续追踪
CallExecuteObservable 类
代码不多,全贴出来
1 | final class CallExecuteObservable<T> extends Observable<Response<T>> { |
而 Converter 是何时发生作用的呢,在 Response
OkhttpCall.execute 方法
1 | public Response<T> execute() throws IOException { |
OkhttpCall.parseResponse 方法
1 | Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException { |
ServiceMethod.toResponse 方法
1 | R toResponse(ResponseBody body) throws IOException { |
这里的 responseConverter 通过 Build.createResponseConverter 创建,通过 responseType 从工厂类通过 responseBodyConverter 获取
而 Converter.convert 方法具体实现交由 GsonResponseBodyConverter 实现,最终通过 gson 相关方式转化
其实除去具体的 CallAdapter 和 Converter 逻辑实现,以图画表现更清晰
结语
Retrofit 通过 okhttp 执行网络请求,通过 CallAdapter 和 Converter 包装上层数据返回,实现了一个完美的中间层封装,用到了动态代理,抽象工厂,策略等模式,结构清晰,代码解耦,是一个非常值得学习和借鉴的开源库。
接下去还有网络请求的真正执行者 okhttp 的代码解析了